package edu.ucla.cs.typecast.ping;

import java.io.*;
import java.net.*;

import edu.ucla.cs.typecast.rmi.TypeCastClient;
import edu.ucla.cs.typecast.rmi.TypeCastServer;

/**
 * Ping receiver. It receives a ping and sends pack a pong.
 */

public class PingReceiverImpl implements PingReceiver {

	private static final long serialVersionUID = 1L;

	/**
	 * mcast TC server to receive pongs from PingSender objects.
	 */

	protected TypeCastServer mcastTcServer;

	/**
	 * Addresses.
	 */

	protected InetAddress privateHost;

	protected int privatePort;

	protected InetAddress publicHost;

	protected int publicPort;

	/**
	 * Creates a ping receiver.
	 * 
	 * @param privateHost
	 *            Unicast hostname of this receiver.
	 * @param privatePort
	 *            Unicast port of this receiver.
	 * @param publicHost
	 *            Multicast hostname of the "environment".
	 * @param publicPort
	 *            Multicast port of the "environment".
	 */

	public PingReceiverImpl(InetAddress privateHost, int privatePort,
			InetAddress publicHost, int publicPort) throws IOException {
		// Record the hosts and ports

		this.privateHost = privateHost;
		this.privatePort = privatePort;
		this.publicHost = publicHost;
		this.publicPort = publicPort;

		// Set up a mcast TC server to receive pongs from PingSender objects

		mcastTcServer = new TypeCastServer(publicHost, publicPort);
		mcastTcServer.export(this);
	}

	/**
	 * Creates a ping receiver.
	 * 
	 * @param privateHost
	 *            Unicast hostname of this receiver.
	 * @param privatePort
	 *            Unicast port of this receiver.
	 * @param publicHost
	 *            Multicast hostname of the "environment".
	 * @param publicPort
	 *            Multicast port of the "environment".
	 */

	public PingReceiverImpl(String privateHost, int privatePort,
			String publicHost, int publicPort) throws IOException {
		this(InetAddress.getByName(privateHost), privatePort, InetAddress
				.getByName(publicHost), publicPort);
	}

	/**
	 * Un-export itself so that it won't act on future datagrams.
	 */

	public void dispose() {
		mcastTcServer.unexport(this);
	}

	public void receivePing(InetAddress senderHost, int senderPort, int seqNum)
			throws IOException {
		// Set up a ucast TC client to send pongs to PingSender objects

		TypeCastClient ucastTcClient = new TypeCastClient(senderHost,
				senderPort);
		PingSender ps = (PingSender) ucastTcClient
				.getTypeCastInvocationHandler(PingSender.class);
		ps.receivePong(privateHost, privatePort, seqNum);
	}
}
